#include <iostream>

// 自定义一个空间配置器allocator
template <typename T>
struct MyAllocator
{
    // 根据传入的size大小分配一块空间
    T* allocate(size_t size)
    {
        return (T*) malloc(sizeof(T) * size);
    }
    // 根据传入的指针,释放空间
    void deAllocate(T* p)
    {
        free(p);
    }
    // 根据传入的数据和空间指针，构造对象
    void construct(T* p, const T& val)
    {
        new (p) T(val); // 定位new 根据p的位置进行对象的拷贝构造
    }
    // 根据传入的指针，进行对象的析构
    void destory(T* p)
    {
        p->~T();  // 调用对象的析构函数
    }

};

// 使用类模板定义vector可以存储任意类型数据
template <typename T, typename Alloc = MyAllocator<T>> // 模板参数列表，可以有多个,默认指定空间配置器，并实例化了空间配置器模板
class MyVector
{
public:
    // 默认构造函数
    MyVector(int size = 5)
    {
        // 开辟一块堆空间
        _first = _allocator.allocate(size);
        _last = _first; // 初始化时候尾指针和首指针指向相同的位置
        _end = _first + size;
    }
    // 析构函数
    ~MyVector()
    {
        // 析构向量空间中有效的内容
        for(T* p = _first; p != _last; p ++)
        {
            _allocator.destory(p);
        }
        // 析构整个向量空间
        _allocator.deAllocate(_first);
        // 将所有指针指向空指针
        _first = _last = _end = nullptr;
    }
    // 拷贝构造函数
    MyVector(const MyVector<T>& src)
    {
        int size = src._end - src._first; // 容器的总容量
        int len = src._last - src._first; // 容器有效对象的长度
        // 生成一个size大小的内存
        _first = _allocator.allocate(size);
        // 将目标容器中的有效数据拷贝到容器中
        for(int i = 0; i < len; i ++)
        {
            _allocator.construct(_first + i, src._first[i]);
        }
        _last = _first + len;
        _end = _first + size;
    }
    // 赋值运算符重载函数
    MyVector<T>& operator=(const MyVector<T>& src)
    {
        // 判断是否是自赋值
        if(this == &src)
            return *this;

        // 将原向量中的有效数据析构
        for(T* p = _first; p != _last; p ++)
        {
            _allocator.destory(p);
        }
        // 删除整个向量空间
        _allocator.deAllocate(_first);
        // 开辟目标向量大小的空间
        int size = src._end - src._first;
        int len = src._last - src._first;
        _first = _allocator.allocate(size);
        // 将目标向量中的对象赋值给原向量
        for(int i = 0; i < len; i ++)
        {
            _allocator.construct(_first + i, src._first[i]);
        }
        return *this;
    }
    void push_back(const T& val)
    {
        if(full())
            expand();
        _allocator.construct(_last, val);
        _last ++;
        
    }
    void pop_back()
    {
        _allocator.destory(--_last);
    }
    T top() const
    {
        return *(_last - 1);
    }
    bool full() const { return _last == _end; }
    bool empty() const { return _first == _last; }
    int size() const { return _end - _first; }
private:
    T* _first;  // 容器的初始指针
    T* _last;   // 容器的最后一个元素指针的后继位置
    T* _end;    // 容器总容量的指针的后继位置
    Alloc _allocator; // 空间配置器
    void expand()
    {
        // 获取原向量容器的尺寸
        int size = _end - _first;
        int len = _last - _first;
        // 开辟新的2倍空间
        T* ptmp = _allocator.allocate(size * 2);
        // 将原来的值赋值给新的值
        for(int i = 0; i < len; i ++)
        {
            _allocator.construct(ptmp + i, _first[i]);
        }
        // 析构掉原有的有效对象
        for(T* p = _first; p != _last; p ++)
            _allocator.destory(p);
        // free掉原有的内存
        _allocator.deAllocate(_first);
        _first = ptmp;
        _end = _first + size * 2;
        _last = _first + len;
    }
};

class Test
{
public:
    Test(int a):ma(a) {  }
    ~Test() {  }
    Test(const Test& t) { ma = t.ma; }
    void show() const { std::cout << ma << std::endl; }
    int ma;
};

int main(int argc, char const *argv[])
{

    MyVector<Test> vec;
    for(int i = 0; i < 10; i ++)
    {
        vec.push_back(Test(i + 1));
    }
    while (!vec.empty())
    {

        vec.top().show();
        vec.pop_back();
    }
    
    std::cout << "----------------" << std::endl;
    return 0;
}
